﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security.Cryptography;
using CommModule.Security;

namespace CommModule.Messages
{
    public class MessageSignature: Convertible
    {
        private String _endpointId;
        private String _remoteEndpointId;
        private String _currentTimestamp;
        private String _messageHash;

        private String _cipheredSignature;

        public MessageSignature() { }

        public MessageSignature(String messageHash, RSACryptoServiceProvider encryptor)
        {
            _endpointId = "WEBSERVER";
            _remoteEndpointId = "CERTCOP";
            _messageHash = messageHash;
            _currentTimestamp = DateTime.Now.Ticks.ToString();

            _cipheredSignature = signMessage(encryptor);
        }

        public String getTimestamp()
        {
            return _currentTimestamp;
        }

        private String signMessage(RSACryptoServiceProvider encryptor)
        {
            String serializedSignature = ObjectSerialization.SerializeObjectAsString(this);

            return AssimEncryption.SignMessage(serializedSignature, encryptor);
        }

        public bool validateSignature(String hashedObject, String remoteEndpointId, String endpointId, String lastReceivedMessageTS, RSACryptoServiceProvider decryptor)
        {
            if (!remoteEndpointId.Equals(_endpointId))
                return false;

            if (!endpointId.Equals(_remoteEndpointId))
                return false;

            if (!_messageHash.Equals(hashedObject))
                return false;

            long longMessageTs = long.Parse(_currentTimestamp);
            long lastMessageTs = long.Parse(lastReceivedMessageTS);
            if (longMessageTs < lastMessageTs)
                return false;

            String cipheredSignature = _cipheredSignature;
            _cipheredSignature = null;

            String serializedSignature = ObjectSerialization.SerializeObjectAsString(this);

            return AssimEncryption.ValidateSignature(serializedSignature, cipheredSignature, decryptor);
        }

        public void ConvertToCanonic(XmlWriter xmlWriter)
        {
            xmlWriter.WriteStartElement("MessageSignature");

            if (_endpointId != null)
            {
                xmlWriter.WriteStartElement("EndpointId");
                xmlWriter.WriteString(_endpointId);
                xmlWriter.WriteEndElement();
            }

            if (_remoteEndpointId != null)
            {
                xmlWriter.WriteStartElement("RemoteEndpointId");
                xmlWriter.WriteString(_remoteEndpointId);
                xmlWriter.WriteEndElement();
            }

            if (_currentTimestamp != null)
            {
                xmlWriter.WriteStartElement("CurrentTimestamp");
                xmlWriter.WriteString(_currentTimestamp);
                xmlWriter.WriteEndElement();
            }

            if (_messageHash != null)
            {
                xmlWriter.WriteStartElement("MessageHash");
                xmlWriter.WriteString(_messageHash);
                xmlWriter.WriteEndElement();
            }

            if (_cipheredSignature != null)
            {
                xmlWriter.WriteStartElement("CipheredSignature");
                xmlWriter.WriteString(_cipheredSignature);
                xmlWriter.WriteEndElement();
            }

            xmlWriter.WriteEndElement();
        }

        public void ConvertFromCanonic(XmlTextReader xmlTextReader)
        {
            xmlTextReader.ReadStartElement();

            if (xmlTextReader.Name == "EndpointId")
            {
                _endpointId = xmlTextReader.ReadElementContentAsString();
            }

            if (xmlTextReader.Name == "RemoteEndpointId")
            {
                _remoteEndpointId = xmlTextReader.ReadElementContentAsString();
            }

            if (xmlTextReader.Name == "CurrentTimestamp")
            {
                _currentTimestamp = xmlTextReader.ReadElementContentAsString();
            }

            if (xmlTextReader.Name == "MessageHash")
            {
                _messageHash = xmlTextReader.ReadElementContentAsString();
            }

            if (xmlTextReader.Name == "CipheredSignature")
            {
                _cipheredSignature = xmlTextReader.ReadElementContentAsString();
            }

            xmlTextReader.ReadEndElement();
        }
    }
}
